<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
    <!-- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">-->
    <title>像素</title>
    <style>
        .colorBlock {
            display: inline-block;
            width: 200px;
            height: 100px;
            text-align: center;
            line-height: 100px;
        }
    </style>
</head>
<body>
<div>
    <canvas id="canvas"></canvas>
    <p id="pText"></p>
    <div id="colorDiv" class="colorBlock"></div>
</div>

<div>
    <canvas id="diyCanvas"></canvas>
    <p>
        <button id="invertbtn">反转色</button>
        <button id="grayscalebtn">灰度图</button>
    </p>
</div>
<div>
    <!-- Learn about this code on MDN: https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas -->

    <canvas id="srcCanvas" width="300" height="227"></canvas>
    <canvas id="zoomCanvas" width="300" height="227"></canvas>
    <div>
        <label for="smoothbtn">
              <input type="checkbox" name="smoothbtn" checked="checked" id="smoothbtn">
              Enable image smoothing
        </label>
    </div>

    <p></p>

    <canvas id="partImgCanvas" width="300" height="227"></canvas>
    <button onclick="covertPart.covert(event)">网点化</button>
</div>
<script>
    //js的imageData.data像素数组为无符号8位整型数组（Uint8ClampedArray）。数组中一个元素是一个通道颜色，依次按照rgba排列。
    //这和java、安卓不同，java直接用int型保存了四个通道的值。因为int型有32位。
    //于是，获取像素矩阵中第（x,y）个像素的方式也不同。java直接是y*width+x
    //js是r = y*4*width+x*4,g=y*4*width+x*4+1,b=y*4*width+x*4+2,a=y*4*width+x*4+3

    function getColorFromCanvas() {

        var img = new Image();

        var canvas = document.getElementById('canvas');
        var colorDiv = document.getElementById('colorDiv');

        var ctx = canvas.getContext('2d');
        // img.crossorigin="anonymous";//
        img.setAttribute("crossOrigin", 'Anonymous');//(待验证)只能同一个协议下跨域。file:///不支持获取http图
        img.onload = function () {
            ctx.drawImage(img, 0, 0);
            img.style.display = 'none';
        };
        img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';

        function pick(event) {
            var x = event.layerX;
            var y = event.layerY;
            var pixel = ctx.getImageData(x, y, 1, 1);
            var data = pixel.data;
            var rgba = 'rgba(' + data[0] + ',' + data[1] +
                ',' + data[2] + ',' + (data[3] / 255) + ')';

            colorDiv.style.background = rgba;
            colorDiv.style.color = "rgb(" + mixCompone(data[0]) + "," + mixCompone(data[1]) + "," + mixCompone(data[2]) + ")";
            colorDiv.textContent = rgba;
        }

        function mixCompone(c) {
            // return Math.sqrt(255 * 255 - c * c);
            return 255 - c;
        }

        canvas.addEventListener('mousemove', pick);

    }

    function diyImg() {
        var img = new Image();
        img.setAttribute("crossOrigin", 'Anonymous');//(待验证)只能同一个协议下跨域。file:///不支持获取http图
        img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';
        //图片请求是异步的，一般网络请求较慢，img.onload 会得到绑定。但如果从缓存中读取极快，可能来不及绑定
        //故有将src=xxx放在onload之后
        if (img.complete) {
            draw(img);
            console.log("来自缓存");
        } else {
            img.onload = function (e) {
                draw(this);
            };
        }


        function draw(img) {
            var canvas = document.getElementById('diyCanvas');
            var ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0, 0);
            img.style.display = 'none';
            var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            var data = imageData.data;

            //反转色
            var invert = function () {
                for (var i = 0; i < data.length; i += 4) {
                    data[i] = 225 - data[i]; // red
                    data[i + 1] = 225 - data[i + 1]; // green
                    data[i + 2] = 225 - data[i + 2]; // blue
                }
                ctx.putImageData(imageData, 0, 0);
            };

            //灰度图
            var grayscale = function () {
                for (var i = 0; i < data.length; i += 4) {
                    var avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
                    data[i] = avg; // red
                    data[i + 1] = avg; // green
                    data[i + 2] = avg; // blue
                }
                ctx.putImageData(imageData, 0, 0);
            };

            var invertbtn = document.getElementById('invertbtn');
            invertbtn.addEventListener('click', invert);
            var grayscalebtn = document.getElementById('grayscalebtn');
            grayscalebtn.addEventListener('click', grayscale);
        }
    }

    function preImg() {
        var img = new Image();
        img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';
        img.onload = function () {
            draw(this);
        };

        function draw(img) {
            var canvas = document.getElementById('srcCanvas');
            var ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0, 0);
            img.style.display = 'none';
            var zoomctx = document.getElementById('zoomCanvas').getContext('2d');

            var smoothbtn = document.getElementById('smoothbtn');
            //抗锯齿设置。不同浏览器不一样
            var toggleSmoothing = function (event) {
                zoomctx.imageSmoothingEnabled = this.checked;
                zoomctx.mozImageSmoothingEnabled = this.checked;
                zoomctx.webkitImageSmoothingEnabled = this.checked;
                zoomctx.msImageSmoothingEnabled = this.checked;
            };
            smoothbtn.addEventListener('change', toggleSmoothing);


            var zoom = function (event) {
                var x = event.layerX;
                var y = event.layerY;
                //取xy上下左右10*10个像素，放大显示。不抗锯齿时，是等间采样算法。抗锯齿时是模糊的，获得更佳预览。
                //等间采样算法放大，适用于需要明显边缘的场景。
                zoomctx.drawImage(canvas, Math.abs(x - 5), Math.abs(y - 5), 10, 10, 0, 0, 200, 200);
            };

            canvas.addEventListener('mousemove', zoom);
        }
    }

    getColorFromCanvas();
    diyImg();
    preImg();


    var covertPart = (function () {

        var img = new Image();
        var canvas = document.getElementById('partImgCanvas');

        var ctx = canvas.getContext('2d');
        img.setAttribute("crossOrigin", 'Anonymous');//(待验证)只能同一个协议下跨域。file:///不支持获取http图
        var data;

        img.onload = function () {
            ctx.drawImage(img, 0, 0);
            data = ctx.getImageData(0, 0, img.width, img.height).data;
        };
        img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';

        function covert(event) {
            console.log(event);
            for (var i = 0; i < data.length; i += 4) {
                if ((i / 32) % 2 === 0) {
                    data[i] = 255 - data[i]; // red
                    data[i + 1] = 255 - data[i + 1]; // green
                    data[i + 2] = 255 - data[i + 2]; // blue
                }
            }

            ctx.putImageData(new ImageData(data,img.width,img.height), 0, 0);
        }

        return {
            covert: covert
        };
    }());
</script>
</body>
</html>